﻿/* ----------------------------------------------------------------------------
 * Copyright (c) Rob Ashton 2009
 *
 * This source code is subject to terms and conditions of the Microsoft Public 
 * License (Ms-PL).
 * 
 * By using this source code in any fashion, you are agreeing to be bound 
 * by the terms of the Microsoft Public License.
 * 
 * To request a copy of the Microsoft Public License, send a request by email
 * to license@mvcex.com
 *
 * This notice must not be removed from this software.
 * ---------------------------------------------------------------------------- */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using site.core.Controllers;
using System.Web.Mvc;
using System.Reflection;
using Moq;
using MvcEx.Controllers;

namespace MvcEx.Tests
{
    [TestFixture]
    public class MvcExControllerFactoryTests
    {
        [Test]
        public void create_empty_controller_and_release_it()
        {       
            var builderSelectorMock = new Mock<IMvcExControllerBuilderSelector>();
            var builderMock = new Mock<IMvcExControllerBuilder>();
            builderMock.Setup(x=>x.GetControllerType(It.IsAny<String>())).Returns(typeof(EmptyController));
            builderSelectorMock.Setup(x => x.GetActiveBuilder()).Returns(builderMock.Object);

            // Create the factory pointing at these dummy objects
            MvcExControllerFactory factory = new MvcExControllerFactory(
                builderSelectorMock.Object,
                null);

            // Request the empty controller
            IController interfaceController = factory.CreateController(null, "FactoryEmpty");

            // Release it
            factory.ReleaseController(interfaceController);
        }

        [Test]
        public void create_controller_when_no_selector_available()
        {
            var builderSelectorMock = new Mock<IMvcExControllerBuilderSelector>();
            builderSelectorMock.Setup(x => x.GetActiveBuilder()).Returns((IMvcExControllerBuilder)null);

            // Create the factory pointing at these dummy objects
            MvcExControllerFactory factory = new MvcExControllerFactory(
                builderSelectorMock.Object,
                null);

            // Request the empty controller
            IController interfaceController = factory.CreateController(null, "FactoryEmpty");

            // Oh, it isn't there!
            Assert.IsNull(interfaceController);
        }

        [Test]
        public void create_invalid_controller()
        {
            var builderSelectorMock = new Mock<IMvcExControllerBuilderSelector>();
            var builderMock = new Mock<IMvcExControllerBuilder>();
            builderMock.Setup(x => x.GetControllerType(It.IsAny<String>())).Returns((Type)null);
            builderSelectorMock.Setup(x => x.GetActiveBuilder()).Returns(builderMock.Object);

            // Create the factory pointing at these dummy objects
            MvcExControllerFactory factory = new MvcExControllerFactory(
                builderSelectorMock.Object,
                null);

            // Request the empty controller
            IController interfaceController = factory.CreateController(null, "FactoryEmpty");

            // Should not have returned it
            Assert.Null(interfaceController);
        }

        [Test]
        public void set_ioc_container()
        {
            MvcExControllerFactory factory = new MvcExControllerFactory(null);
            Mock<IIocContainer> container = new Mock<IIocContainer>();
            factory.SetIocContainer(container.Object);
            Assert.AreEqual(factory.IocContainer, container.Object);
        }

        [Test]
        public void set_valid_base_type()
        {
            MvcExControllerFactory factory = new MvcExControllerFactory(null);
            factory.SetBaseControllerType(typeof(EmptyController));
        }

        [Test]
        public void set_invalid_base_type()
        {
            MvcExControllerFactory factory = new MvcExControllerFactory(null);
            Assert.Throws<InvalidOperationException>(() =>{
                factory.SetBaseControllerType(typeof(InvalidController));
            });
        }

        public class InvalidController : Controller
        {
        }
        
        public class EmptyController : MvcExController
        {
            public EmptyController(IIocContainer container) : base(container)
            {

            }
        }
    }
}
